<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- 
    计算属性：
      概念：
        基于现有数据通过一些计算得出一个新的数据，用于到模板中使用，得到的数据就叫做计算属性。

      解决的问题：
        1. 模板中太重的逻辑代码
        2. 复用的问题

      语法：
        computed: {
          key1: value1,
          key2: value2
        }

          - key1 | key2:  最终要使用的计算属性的数据，他们可以直接拿到模板中使用类似与 data 选项中的数据
          - value1 | value2: 
              - 一个函数，该函数就是用于计算值的一个 get 函数。
              - 一个对象，对象中需要包含有一个 get 函数

      get函数：
        1. 默认执行一次
        2. 需要有返回值，返回值的内容就是计算属性的值
        3. 函数内使用到数据会作为该计算属性的一个依赖项，当依赖项发生变化时，该get函数会重新执行，最终计算属性的值也会跟着变化
        4. 不能有副作用，不能写 异步逻辑，不能操作DOM，不能改变外部的其他数据

      计算属性的特点：
        1. 计算属性是一个只读的数据，不能修改。
        2. 有缓存，get函数默认执行一次，返回值给缓存起来了，后续多次使用该计算属性不会触发get函数的多次执行，而是使用上一次执行的缓存结果。

      可写的计算属性：
        语法使用 对象的形式，除了提供必须的 get 属性之外，再提供一个 set 属性。但是最终还是不能直接他，而是间接的修改他的依赖项。

      基础案例：
        1. 反转字符串
        2. 首字母大写

      面试题：
        1. 计算属性与函数的区别：
          计算属性有缓存，性能更优秀。
   -->

    <div id="app">
      <p>{{ msg }}</p>
      <!-- <p>{{ msg.split('').reverse().join('') }}</p> -->
      <!-- <p>{{ msg.split('').reverse().join('') }}</p> -->
      <p>{{ reverseMsg }}</p>
      <p>{{ reverseMsg }}</p>
      <p>{{ reverseMsg }}</p>
      <p>{{ revMsg() }}</p>
      <p>{{ revMsg() }}</p>
      <p>{{ revMsg() }}</p>

      <button @click="reverseMsg = '张三'">修改 reverseMsg</button>

      <p>{{ code }}</p>
      <!-- <p>{{ code[0].toUpperCase() + code.slice(1) }}</p> -->
      <p>{{ upCode }}</p>
      <button @click="upCode = 'Abcd'">修改 upCode = Abcd</button>
      <button @click="upCode = 'Efgh'">修改 upCode = Efgh</button>
    </div>

    <script src="../lib/vue-3.js"></script>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            msg: "Hello",
            code: "world",
          };
        },
        computed: {
          // reverseMsg() {
          //   console.log("计算 reverseMsg");
          //   return this.msg.split("").reverse().join("");
          // },
          reverseMsg: {
            get() {
              console.log("计算 reverseMsg");
              return this.msg.split("").reverse().join("");
            },

            // reverseMsg = '张三'
            //      value = '张三'
            set(value) {
              this.msg = value.split("").reverse().join("");
            },
          },
          upCode: {
            get: function () {
              return this.code[0].toUpperCase() + this.code.slice(1);
            },

            // this.upCode = 'Abcd'
            //      value = 'Abcd'
            set: function (value) {
              console.log("upCode set", value);
              // 修改他的依赖项，从而导致 上面的 get 函数再次触发，达到修改了计算属性的效果
              this.code = value[0].toLowerCase() + value.slice(1);
            },
          },
        },
        methods: {
          revMsg() {
            console.log("函数 revMsg");
            return this.msg.split("").reverse().join("");
          },
        },
      });

      app.mount("#app");
    </script>
  </body>
</html>
